package com.panopset.sf;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.math.BigDecimal;

import javax.swing.JMenuBar;

import com.panopset.Logger;
import com.panopset.compat.MathUtil;
import com.panopset.compat.Strings;
import com.panopset.compat.Zombie;

/**
 * Message Menubar provides drawing capability in the right hand portion of the
 * menubar that would otherwise be wasted space.
 *
 * @author Karl Dinwiddie.
 */
public final class MessageMenuBar {
	
	private JMenuBar mb;
	
	public JMenuBar getMenuBar() {
		if (mb == null) {
			mb = new JMenuBar() {

				@Override
			    public void paint(final Graphics g) {
			    	super.paint(g);
			        if (Strings.isPopulated(msg)) {
			            paintMessage(g);
			        } else {
			            paintMemory(g);
			        }
			    }

				/**
				 * 1L.
				 */
				private static final long serialVersionUID = 1L;
			};
			

		}
		return mb;
	}
	private String msg;
	private Color clr;
	
	/**
	 * @param value Message value.
	 */
	public void dspmsg(final String value) {
		msg = value;
		clr = Color.GREEN;
	}
	
	/**
	 * @param value Message value.
	 */
	public void dspwrn(final String value) {
		msg = value;
		clr = Color.YELLOW;
	}
	
	/**
	 * @param value Message value.
	 */
	public void dsperr(final String value) {
		msg = value;
		clr = Color.RED;
	}

	FontManager fm = FontManager.getInstance();
    /**
     * 90.
     */
    private static final int MEMORY_ALERT_AT_90 = 90;

    /**
     * Half second refresh rate should do it.
     */
    private static final int REFRESH_RATE = 500;

    /**
     * Constructor.
     */
    public MessageMenuBar() {
        super();
        new Thread("painter") {

            @Override
            public void run() {
                while (Zombie.isActive()) {
                    if (getMenuBar().isShowing()) {
                    	getMenuBar().repaint();
                    }
                    try {
                        Thread.sleep(REFRESH_RATE);
                    } catch (InterruptedException e) {
                        log(e);
                    }
                }
            }
        }

        .start();
        new Thread("caps") {
            private boolean caps;

            @Override
            public void run() {
                while (Zombie.isActive()

                && capsLockCheckAvailable) {
                    boolean newCaps = isCapsLocked();
                    if (newCaps != caps) {
                    	getMenuBar().repaint();
                    }
                    caps = newCaps;
                    try {
                        Thread.sleep(REFRESH_RATE);
                    } catch (InterruptedException e) {
                        log(e);
                    }
                }
            }
        }

        .start();
        getMenuBar().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(final MouseEvent e) {
                msg = "";
                getMenuBar().repaint();
            }
        });
    }

    /**
     * Paint available memory.
     *
     * @param g
     *            Graphics.
     */
    private void paintMemory(final Graphics g) {
        long fr = Runtime.getRuntime().freeMemory();
        long tm = Runtime.getRuntime().totalMemory();
        long mm = Runtime.getRuntime().maxMemory();
        long um = tm - fr;
        MathUtil.Percentage percentage = MathUtil.percent(um, mm, 2);
        boolean alert = percentage.getValue().compareTo(
                new BigDecimal(MEMORY_ALERT_AT_90)) > 0;
        g.setColor(Color.GRAY);
        if (alert) {
            g.setColor(Color.RED);
        }
        int w = (getMenuBar().getSize().width - getMenuBar().getLocation().x) / 2;
        int x = getMenuBar().getLocation().x + w;
        int y = getMenuBar().getLocation().y + 1;
        int h = getMenuBar().getSize().height - 2;
        g.fillRect(x, y, w, h);
        g.setColor(Color.LIGHT_GRAY);
        if (alert) {
            g.setColor(Color.BLACK);
        }
        g.fillRect(x + 1, y + 1, w - 2, h - 2);
        g.setFont(fm.getPlainArial());
        g.setColor(Color.DARK_GRAY);
        if (alert) {
            g.setColor(Color.RED);
        }
        g.drawString("Memory: " + um + " of " + mm + ", " + percentage
                + "% used.", w + TEXT_OFFSET_X, h + TEXT_OFFSET_Y);

        drawCaps(g, h);
    }

    /**
     *
     * @param g
     *            Graphics.
     * @param h
     *            Height.
     */
    private void drawCaps(final Graphics g, final int h) {
        if (isCapsLocked()) {
            g.setColor(Color.ORANGE);
            g.drawString("Caps", getMenuBar().getSize().width
                    - (getMenuBar().getLocation().x + CL_OFFSET), h + TEXT_OFFSET_Y);
        }
    }

    /**
     * Caps loc offset.
     */
    private static final int CL_OFFSET = 40;

    /**
     * Caps lock check available flag.
     */
    private static boolean capsLockCheckAvailable = true;

    /**
     * @return false if caps lock state not available.
     */
    static boolean isCapsLocked() {
        try {
            return java.awt.Toolkit.getDefaultToolkit().getLockingKeyState(
                    java.awt.event.KeyEvent.VK_CAPS_LOCK);
        } catch (Exception ex) {
            capsLockCheckAvailable = false;
        }
        return false;
    }

    /**
     * Paint message.
     *
     * TODO Use flywheel graphics.
     *
     * @param g
     *            Graphics.
     */
    private void paintMessage(final Graphics g) {
        g.setColor(Color.GRAY);
        int w = (getMenuBar().getSize().width - getMenuBar().getLocation().x) / 2;
        int x = getMenuBar().getLocation().x + w;
        int y = getMenuBar().getLocation().y + 1;
        int h = getMenuBar().getSize().height - 2;
        g.fillRect(x, y, w, h);
        g.setColor(Color.BLACK);
        g.fillRect(x + 1, y + 1, w - 2, h - 2);
        g.setFont(fm.getPlainArial());
        g.setColor(clr);
        g.drawString(msg, w + MathUtil.THREE, h - MathUtil.FOUR);
        drawCaps(g, h);
    }

    /**
     * X text offset is 3.
     */
    private static final int TEXT_OFFSET_X = 3;

    /**
     * Y text offset -4.
     */
    private static final int TEXT_OFFSET_Y = -4;

    /**
     * Serial Version ID.
     */
    private static final long serialVersionUID = 0L;

	private void log(Throwable t) {
		Logger.log(t);
	}
}
